package com.dyna.demo.device;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dyna.core.utils.ConvertUtil;
import com.dyna.core.utils.ObjectUtil;
import com.dyna.core.utils.PageUtil;
import com.dyna.demo.device.convert.DcDeviceInfoConvert;
import com.dyna.demo.device.domain.entity.DcDevicesInfo;
import com.dyna.demo.device.domain.entity.DeviceInfo;
import com.dyna.demo.device.domain.req.DcDeviceInfoReq;
import com.dyna.demo.device.domain.resp.DcDeviceInfoResp;
import com.dyna.demo.device.mapper.DeviceInfoMapper;
import com.dyna.domain.req.PageParam;
import com.dyna.domain.resp.PageResult;
import com.dyna.domain.resp.R;
import com.dyna.utils.RdsUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Point;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Api("demo模块/demo/设备信息")
@RestController
@RequestMapping("/device")
public class DeviceInfoController {

    @Autowired
    private DeviceInfoService deviceInfoService;

    @ApiOperation("距离点位查询")
    @RequestMapping("/distance")
    public R<List<DeviceInfo>> distance(@RequestParam("code") String code) {
        return R.data(deviceInfoService.distance(code));
    }

    @ApiOperation("根据设备code查询设备名称")
    @RequestMapping("/getDeviceNameByCode")
    public R<String> getDeviceNameByCode(@RequestParam("code") String code) {
        return R.data(deviceInfoService.getDeviceNameByCode(code));
    }

    @ApiOperation("查询所有设备信息")
    @PostMapping("/getAllDeviceInfoList")
    public R<List<DcDeviceInfoResp>> getAllDeviceInfoList(@RequestBody DcDeviceInfoReq req) {
        List<DcDevicesInfo> deviceInfoList = deviceInfoService.getAllDeviceInfoList(req);
        long startTime = System.currentTimeMillis();
        List<DcDeviceInfoResp> respList = ConvertUtil.convertList(deviceInfoList, DcDeviceInfoConvert.DEVICE_CONVERTER);
        long endTime = System.currentTimeMillis();
        System.out.println("转换耗时："+(endTime-startTime));
        return R.data(respList);
    }

    @ApiOperation("分页查询设备信息")
    @PostMapping("/getDeviceInfoPage")
    public R<PageResult<DcDeviceInfoResp>> getDeviceInfoPage(@RequestBody DcDeviceInfoReq req) {
        PageResult<DcDevicesInfo> infoPage = deviceInfoService.getDeviceInfoPage(req);
        long startTime = System.currentTimeMillis();
        PageResult<DcDeviceInfoResp> pageResult = PageUtil.convertPageResult(infoPage, DcDeviceInfoConvert.DEVICE_CONVERTER);
        long endTime = System.currentTimeMillis();
        System.out.println("转换耗时："+(endTime-startTime));
        return R.data(pageResult);
    }

}

@Slf4j
@Service
class DeviceInfoService {

    private final DeviceInfoMapper deviceInfoMapper;

    @Autowired
    public DeviceInfoService(DeviceInfoMapper deviceInfoMapper) {
        this.deviceInfoMapper = deviceInfoMapper;
    }

    public List<DeviceInfo> distance(String code) {
        List<DeviceInfo> list;
        String deviceListCacheStr = RdsUtil.get("device_list");
        if (StrUtil.isNotBlank(deviceListCacheStr)) {
            log.info("从缓存获取设备数据...");
            list = JSON.parseArray(deviceListCacheStr, DeviceInfo.class);
        }else {
            log.info("从数据库查询设备数据...");
            list = deviceInfoMapper.queryAllDeviceInfo();
            RdsUtil.set("device_list", JSON.toJSONString(list), 10, TimeUnit.MINUTES);
        }
        Map<String, Point> map = list.stream()
                .limit(200)
                .collect(
                        Collectors.toMap(
                                DeviceInfo::getCode,
                                k -> new Point(k.getLongitude().doubleValue(), k.getLatitude().doubleValue())
                        )
                );
        Long result = RdsUtil.stringRedisTemplate.opsForGeo().add("device", map);
        log.info("缓存设备经纬度信息:::{}", result);

        List<DeviceInfo> deviceInfoList = list.stream().limit(200).collect(Collectors.toList());
        for (DeviceInfo deviceInfo : deviceInfoList) {
            // 计算地理位置
            Distance distance = RdsUtil.distance("device", code, deviceInfo.getCode());
            log.info("点位【{}】和点位【{}】之间的距离为:::{}，单位是【{}】",
                    code,
                    deviceInfo.getCode(),
                    distance.getValue(),
                    distance.getUnit()
            );
        }
        return list;
    }

    public String getDeviceNameByCode(String code) {
        return deviceInfoMapper.queryDeviceInfoByCode(code);
    }

    public List<DcDevicesInfo> getAllDeviceInfoList(DcDeviceInfoReq req) {
        return deviceInfoMapper.selectList(req);
    }


    public PageResult<DcDevicesInfo> getDeviceInfoPage(DcDeviceInfoReq req) {
        PageParam pageParam = PageUtil.getPageParam();
        LambdaQueryWrapper<DcDevicesInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StrUtil.isNotBlank(req.getCode()), DcDevicesInfo::getCode, req.getCode());
        queryWrapper.eq(StrUtil.isNotBlank(req.getName()), DcDevicesInfo::getName, req.getName());
        queryWrapper.eq(ObjectUtil.isNotNull(req.getStatus()), DcDevicesInfo::getStatus, req.getStatus());
        queryWrapper.eq(ObjectUtil.isNotNull(req.getType()), DcDevicesInfo::getType, req.getType());
        queryWrapper.ge(ObjectUtil.isNotNull(req.getStartTime()), DcDevicesInfo::getCreateTime, req.getStartTime());
        queryWrapper.le(ObjectUtil.isNotNull(req.getEndTime()), DcDevicesInfo::getUpdateTime, req.getEndTime());
        return deviceInfoMapper.selectPage(pageParam, queryWrapper);
    }

}


